package br.com.guarana.business.service;

import br.com.guarana.business.model.Segurado;
import br.com.guarana.business.model.SeguradoApolice;
import br.com.guarana.business.model.SeguradoApoliceCobertura;
import br.com.guarana.business.model.SeguradoBeneficiario;
import br.com.guarana.util.Util;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.persistence.Query;

/**
 *
 * @author 
 */
public class SeguradoService extends PadraoService {

    public Segurado salvar(Segurado segurado) {
        try {
            this.getDAO().getEntityManager().getTransaction().begin();
            
            //trata Apolices~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            //se a segurado já existe
            if (segurado.getId() != null && segurado.getId() != 0) {

                //busca os itens da lista do banco de dados - itens já gravados
                List<SeguradoApolice> listaSeguradoApolicesAntiga = this.findSegurado(segurado.getId()).getListaDeApolices();

                //seta o segurado na lista
                for (SeguradoApolice atendApolice : segurado.getListaDeApolices()) {
                    atendApolice.setSegurado(segurado);
                    
                    //Itens da Apolice~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                    if (atendApolice.getId() != null && atendApolice.getId() != 0){
                        
                        //Seto o item na encomenda
                        for (SeguradoApoliceCobertura item : atendApolice.getListaDeCoberturas()) {
                            item.setSeguradoApolice(atendApolice);
                        }
                        
                        //busca os itens do banco de dados - itens já gravados
                        List<SeguradoApoliceCobertura> listaItemAntiga = this.buscaItensDaApolice(atendApolice.getId());
                        
                        //para cada item da lista antiga, preciso verificar se tem na lista nova, caso não excluir
                        for (SeguradoApoliceCobertura item : listaItemAntiga) {
                            if (!atendApolice.getListaDeCoberturas().contains(item)) {
                                this.getDAO().excluir(item);
                            }
                        }                                                
                    } else {
                        //Seto o item na encomenda
                        for (SeguradoApoliceCobertura item : atendApolice.getListaDeCoberturas()) {
                            item.setSeguradoApolice(atendApolice);
                        }
                        
                    }
                    //----------------------------------------------------------                                                                                
                }

                //para cada item da lista antiga, preciso verificar se tem na lista nova, caso não excluir
                for (SeguradoApolice itemAntigo : listaSeguradoApolicesAntiga) {
                    if (!segurado.getListaDeApolices().contains(itemAntigo)) {
                        this.getDAO().excluir(itemAntigo);
                    }
                }

            //se o segurado é nova
            } else {
                //seta o segurado
                if (segurado.getListaDeApolices() != null) {
                    for (SeguradoApolice atendApolice : segurado.getListaDeApolices()) {
                        atendApolice.setSegurado(segurado);
                        
                        //Seto o item na encomenda------------------------------
                        for (SeguradoApoliceCobertura item : atendApolice.getListaDeCoberturas()) {
                            item.setSeguradoApolice(atendApolice);
                        }
                        
                    }
                }
            }
            //------------------------------------------------------------------
                        
            //trata Beneficiários~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            //se a segurado já existe
            if (segurado.getId() != null && segurado.getId() != 0) {

                //busca os itens da lista do banco de dados - itens já gravados
                List<SeguradoBeneficiario> listaSeguradoBeneficiariosAntiga = this.findSegurado(segurado.getId()).getListaDeBeneficiarios();

                //seta o segurado na lista de seguradoProdutos
                for (SeguradoBeneficiario itemDetalhe : segurado.getListaDeBeneficiarios()) {
                    itemDetalhe.setSegurado(segurado);
                }

                //para cada item da lista antiga, preciso verificar se tem na lista nova, caso não excluir
                for (SeguradoBeneficiario itemAntigo : listaSeguradoBeneficiariosAntiga) {
                    if (!segurado.getListaDeBeneficiarios().contains(itemAntigo)) {
                        this.getDAO().excluir(itemAntigo);
                    }
                }

            //se o segurado é nova
            } else {
                //seta o segurado nos seguradoProdutos
                if (segurado.getListaDeBeneficiarios() != null) {
                    for (SeguradoBeneficiario itemDetalhe : segurado.getListaDeBeneficiarios()) {
                        itemDetalhe.setSegurado(segurado);
                    }
                }
            }
            //------------------------------------------------------------------                                 
            
            
            //salva segurado com tabelas filhas
            this.getDAO().salvar(segurado);
            this.getDAO().getEntityManager().getTransaction().commit();

            return segurado;

        } catch (final Exception e) {
            this.getDAO().getEntityManager().getTransaction().rollback();
            RuntimeException myRuntime = new RuntimeException() {

                public String getMessage() {
                    return e.getMessage();
                }
            };
            throw myRuntime;
        }
    }

    public void excluir(Segurado segurado) {
        try {
            this.getDAO().getEntityManager().getTransaction().begin();
            this.getDAO().excluir(segurado);
            this.getDAO().getEntityManager().getTransaction().commit();

        } catch (Exception e) {
            e.printStackTrace();
            this.getDAO().getEntityManager().getTransaction().rollback();
        }
    }

    public Segurado findSegurado(int id) {
        return (Segurado) this.getDAO().find(Segurado.class, id);
    }
        
    
    public List<Segurado> buscaTodosSegurados() {
        StringBuilder sFrase = new StringBuilder("SELECT r FROM Segurado r ORDER BY r.dataSegurado");
        Query query = this.getDAO().getEntityManager().createQuery(sFrase.toString());
        List<Segurado> listaSegurado = query.getResultList();                
        return listaSegurado;
    }
   
    
    public List<Segurado> buscaSeguradosComFiltros(
            String situacao, 
            String cpf,
            String sexo,
            
            int idEstipulante,
            int idCidade,
            
            String nomeSegurado,
            String nomeConjuge,
                        
            Date dataNascimentoInicio, 
            Date dataNascimentoFim,             
            
            String observacao, 
            
            int pagQtdeRegistro, 
            int pagPosicaoInicial
        ) {
        //formatador para datas
        DateFormat formataData = new SimpleDateFormat("yyyy-MM-dd");
        StringBuilder sFiltros = new StringBuilder();
                
        //filtros        
        if (situacao != null) {
            sFiltros.append(Util.colocaWhereOuAnd(sFiltros.toString()) + " r.situacao = '" + situacao + "'");
        }        
        if (cpf != null) {
            sFiltros.append(Util.colocaWhereOuAnd(sFiltros.toString()) + " r.cpf = '" + cpf + "'");
        }        
        if (sexo != null) {
            sFiltros.append(Util.colocaWhereOuAnd(sFiltros.toString()) + " r.sexo = '" + sexo + "'");
        }        
        
        if (idEstipulante != 0) {
            sFiltros.append(Util.colocaWhereOuAnd(sFiltros.toString()) + " r.estipulante.id = " + idEstipulante);
        }
        
        if (idCidade != 0) {
            sFiltros.append(Util.colocaWhereOuAnd(sFiltros.toString()) + " r.cidadeResidencial.id = " + idCidade);
        }        
        
        if (nomeSegurado != null) {
            sFiltros.append(Util.colocaWhereOuAnd(sFiltros.toString()) + " UPPER(r.nome) LIKE '%" + nomeSegurado.toUpperCase().trim() + "%'");
        }        
        
        if (nomeConjuge != null) {
            sFiltros.append(Util.colocaWhereOuAnd(sFiltros.toString()) + " UPPER(r.nomeConjuge) LIKE '%" + nomeConjuge.toUpperCase().trim() + "%'");
        }        

        if (dataNascimentoInicio != null) {
            sFiltros.append(Util.colocaWhereOuAnd(sFiltros.toString()) + " r.dataNascimento >= '" + formataData.format(dataNascimentoInicio) + "'");
        }

        if (dataNascimentoFim != null) {
            sFiltros.append(Util.colocaWhereOuAnd(sFiltros.toString()) + " r.dataNascimento <= '" + formataData.format(dataNascimentoFim) + "'");
        }
        
        if (observacao != null) {
            sFiltros.append(Util.colocaWhereOuAnd(sFiltros.toString()) + " UPPER(r.observacao) LIKE '%" + observacao.toUpperCase().trim() + "%'");
        }        
        
        //query consulta
        Query query = this.getDAO().getEntityManager().createQuery("SELECT r FROM Segurado r " + sFiltros.toString() + " ORDER BY r.nome");
        query.setHint("toplink.refresh", "true");
        query.setFirstResult(pagPosicaoInicial);
        query.setMaxResults(pagQtdeRegistro);
        List<Segurado> listaSegurados = query.getResultList();
        
        //query paginacao
        Query queryTotal = this.getDAO().getEntityManager().createQuery("SELECT r FROM Segurado r " + sFiltros.toString());
        queryTotal.setHint("toplink.refresh", "true");
        List<Segurado> listaTotal = queryTotal.getResultList();
        Integer totalRegistro = 0;
        if (listaTotal.size() > 0) {
            totalRegistro = listaTotal.size();
        }
        //coloca a qtde de registros total no primeiro registro
        if (listaSegurados.size() > 0) {
            listaSegurados.get(0).setQtdeRegistros(totalRegistro);
        }

        return listaSegurados;
    }
    
    public List gerarRelatorioSegurados() {
        List listaDeDados = this.buscaTodosSegurados();
        return listaDeDados;
    }    
    
    
    /**************************************************
    Rotinas para SeguradoBeneficiario
     **************************************************/
    public SeguradoBeneficiario findSeguradoBeneficiario(int id) {
        return (SeguradoBeneficiario) this.getDAO().getEntityManager().find(SeguradoBeneficiario.class, id);
    }

    public List<SeguradoBeneficiario> buscaBeneficiariosDoSegurado(int idSegurado) {
        StringBuilder sFrase = new StringBuilder("SELECT r FROM SeguradoBeneficiario r WHERE r.segurado.id = :idSegurado ORDER BY r.id");
        Query query = this.getDAO().getEntityManager().createQuery(sFrase.toString());
        query.setParameter("idSegurado", idSegurado);
        List<SeguradoBeneficiario> listaSeguradoBeneficiarios = query.getResultList();
        return listaSeguradoBeneficiarios;
    }

    public void salvarSeguradoBeneficiario(SeguradoBeneficiario encomendaCategoria) {
        try {
            this.getDAO().getEntityManager().getTransaction().begin();
            this.getDAO().salvar(encomendaCategoria);
            this.getDAO().getEntityManager().getTransaction().commit();
            
        } catch (Exception e) {
            e.printStackTrace();
            this.getDAO().getEntityManager().getTransaction().rollback();
        }
    }
    
    public void excluirSeguradoBeneficiario(SeguradoBeneficiario encomendaCategoria) {
        try {
            this.getDAO().getEntityManager().getTransaction().begin();
            this.getDAO().excluir(encomendaCategoria);
            this.getDAO().getEntityManager().getTransaction().commit();
            
        } catch (Exception e) {
            e.printStackTrace();
            this.getDAO().getEntityManager().getTransaction().rollback();
        }
    }
                
    /**************************************************
    Rotinas para SeguradoApolice
    **************************************************/
    public SeguradoApolice findSeguradoApolice(int id) {
        return (SeguradoApolice) this.getDAO().getEntityManager().find(SeguradoApolice.class, id);
    }

    public List<SeguradoApolice> buscaApolicesDoSegurado(int idSegurado) {
        StringBuilder sFrase = new StringBuilder("SELECT r FROM SeguradoApolice r WHERE r.segurado.id = :idSegurado ORDER BY r.id");
        Query query = this.getDAO().getEntityManager().createQuery(sFrase.toString());
        query.setParameter("idSegurado", idSegurado);
        List<SeguradoApolice> listaSeguradoApolices = query.getResultList();
        return listaSeguradoApolices;
    }

    public void salvarSeguradoApolice(SeguradoApolice seguradoApolice) {
        try {
            this.getDAO().getEntityManager().getTransaction().begin();
            this.getDAO().salvar(seguradoApolice);
            this.getDAO().getEntityManager().getTransaction().commit();
            
        } catch (Exception e) {
            e.printStackTrace();
            this.getDAO().getEntityManager().getTransaction().rollback();
        }
    }
    
    public void excluirSeguradoApolice(SeguradoApolice seguradoApolice) {
        try {
            this.getDAO().getEntityManager().getTransaction().begin();
            this.getDAO().excluir(seguradoApolice);
            this.getDAO().getEntityManager().getTransaction().commit();
            
        } catch (Exception e) {
            e.printStackTrace();
            this.getDAO().getEntityManager().getTransaction().rollback();
        }
    }
    
    /**************************************************
    Rotinas para SeguradoApoliceCobertura
    **************************************************/
    public SeguradoApoliceCobertura findSeguradoApoliceCobertura(int id) {
        return (SeguradoApoliceCobertura) this.getDAO().getEntityManager().find(SeguradoApoliceCobertura.class, id);
    }

    public List<SeguradoApoliceCobertura> buscaItensDaApolice(int idSeguradoApolice) {
        StringBuilder sFrase = new StringBuilder("SELECT r FROM SeguradoApoliceCobertura r WHERE r.seguradoApolice.id = :idSeguradoApolice ORDER BY r.id");
        Query query = this.getDAO().getEntityManager().createQuery(sFrase.toString());
        query.setParameter("idSeguradoApolice", idSeguradoApolice);
        List<SeguradoApoliceCobertura> listaSeguradoApoliceCoberturas = query.getResultList();
        return listaSeguradoApoliceCoberturas;
    }

    public void salvarSeguradoApoliceCobertura(SeguradoApoliceCobertura seguradoApolice) {
        try {
            this.getDAO().getEntityManager().getTransaction().begin();
            this.getDAO().salvar(seguradoApolice);
            this.getDAO().getEntityManager().getTransaction().commit();
            
        } catch (Exception e) {
            e.printStackTrace();
            this.getDAO().getEntityManager().getTransaction().rollback();
        }
    }
    
    public void excluirSeguradoApoliceCobertura(SeguradoApoliceCobertura seguradoApolice) {
        try {
            this.getDAO().getEntityManager().getTransaction().begin();
            this.getDAO().excluir(seguradoApolice);
            this.getDAO().getEntityManager().getTransaction().commit();
            
        } catch (Exception e) {
            e.printStackTrace();
            this.getDAO().getEntityManager().getTransaction().rollback();
        }
    }
        


    /********************************************************************
    TESTES - TESTES - TESTES - TESTES - TESTES - TESTES - TESTES - TESTES
     ********************************************************************/
    public static void main(String[] args) {
        SeguradoService main = new SeguradoService();
        
        List<Segurado> listaSegurados = main.buscaSeguradosComFiltros("A", null, "M", 0, 0, "jo", null, null, null, "oi", 10, 0);
        for (Segurado segurado : listaSegurados) {
            System.out.println(segurado.getNome());
        }
        
        
    }
}

